using System;
using System.Collections.Generic;
using System.Text;
using System.Workflow.Runtime;
using System.Diagnostics;
using System.Workflow.Activities;
using System.Threading;
using System.Collections.ObjectModel;

namespace Incubator.OTWorkflow
{
	public class OTWorkflowRunner
	{
        WorkflowRuntime workflowRuntime;
        OTStateService otSvc;
        Dictionary<string, StateMachineWorkflowInstance> stateMachineInstances;

        public event EventHandler<WorkflowEventArgs> OnWorkflowIdled;
        public event EventHandler<WorkflowEventArgs> OnWorkflowCompleted;

        public OTWorkflowRunner(OTStateService svc)
        {
            otSvc = svc;
            stateMachineInstances = new Dictionary<string, StateMachineWorkflowInstance>();
            workflowRuntime = new WorkflowRuntime();
            workflowRuntime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(workflowRuntime_WorkflowCompleted);
            workflowRuntime.WorkflowIdled += new EventHandler<WorkflowEventArgs>(workflowRuntime_WorkflowIdled);
            workflowRuntime.WorkflowStarted += new EventHandler<WorkflowEventArgs>(workflowRuntime_WorkflowStarted);
            workflowRuntime.WorkflowTerminated += new EventHandler<WorkflowTerminatedEventArgs>(workflowRuntime_WorkflowTerminated);

            ExternalDataExchangeService dataExchange = new ExternalDataExchangeService();
            workflowRuntime.AddService(dataExchange);
            dataExchange.AddService(otSvc);
        }

        public Guid InitializeStateMachine(string codOt)
        {
            
            WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(OTStateMachine));            

            stateMachineInstances.Add(codOt, new StateMachineWorkflowInstance(workflowRuntime, instance.InstanceId));
            instance.Start();                     
            return instance.InstanceId;
        }

        public Guid CreateOtStateEnCurso(string codOt)
        {
            WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(OTStateMachine));
            StateMachineWorkflowInstance smInstance = new StateMachineWorkflowInstance(workflowRuntime, instance.InstanceId);
            stateMachineInstances.Add(codOt, smInstance);
            instance.Start();
            smInstance.SetState("OTEnCurso");            
            return instance.InstanceId;
            
        }

        public Guid CreateOtStateAsignada(string codOt)
        {
            WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(OTStateMachine));
            StateMachineWorkflowInstance smInstance = new StateMachineWorkflowInstance(workflowRuntime, instance.InstanceId);
            stateMachineInstances.Add(codOt, smInstance);
            instance.Start();
            smInstance.SetState("OTAsignada");
            return instance.InstanceId;

        }

        public ReadOnlyCollection<StateActivity> GetAllStates(string codOt)
        {
            return stateMachineInstances[codOt].States;            
        }

        public string GetNextState(string codOt)
        {
            ReadOnlyCollection<string> possibleStates = stateMachineInstances[codOt].PossibleStateTransitions;

            if (possibleStates.Count < 1)
            {
                DebugMsg(" Error no se ha podido recuperar el estado de la ot" + codOt);
                return "";
            }
            return possibleStates[0];            
        }

        public string GetCurrentState(string codigoOt)
        {
            return stateMachineInstances[codigoOt].CurrentStateName;
        }

        #region WF Events

        void workflowRuntime_WorkflowIdled(object sender, WorkflowEventArgs e)
        {
            DebugMsg("WF Idled");

            if (OnWorkflowIdled != null)
            {
                OnWorkflowIdled(this, e);
            }
        }

        void workflowRuntime_WorkflowTerminated(object sender, WorkflowTerminatedEventArgs e)
        {
            DebugMsg("WF Terminated: " + e.Exception.ToString());
        }

        void workflowRuntime_WorkflowStarted(object sender, WorkflowEventArgs e)
        {
            DebugMsg("WF Started");
        }

       

        void workflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)
        {
            DebugMsg("WF Completed");
            if (OnWorkflowCompleted != null)
            {
                OnWorkflowCompleted(this, e);
            }
        }

        void DebugMsg(string s)
        {
            Debug.WriteLine(Thread.CurrentThread.ManagedThreadId + " " + s);
        }
        #endregion

	}
}
